package com.luom.fsp.job.cycle;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.luom.fsp.job.once.SalesStatisticOnce;
import com.luom.fsp.mapper.OrderMapper;
import com.luom.fsp.mapper.ProductMapper;
import com.luom.fsp.mapper.ProductSKUMapper;
import com.luom.fsp.model.entity.Order;
import com.luom.fsp.model.entity.Product;
import com.luom.fsp.model.entity.ProductSKU;
import com.luom.fsp.model.enums.OrderPayStatusEnum;
import com.luom.fsp.model.enums.OrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.luom.fsp.constant.RedisConstant.PRODUCT_SALES_STATISTIC_KEY;
import static com.luom.fsp.constant.RedisConstant.SKU_SALES_STATISTIC_KEY;

/**
 * 销量统计定时任务
 */
@Slf4j
@Component
public class SalesStatistic {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private ProductSKUMapper productSKUMapper;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Scheduled(cron = "0 40 23 * * ?")
    public void salesStatistic() {
        this.synchronizeOrders();
    }

    public void synchronizeOrders(){
        log.info("统计开始");

        // 1. 删除原有销量统计数据
        Set<String> keys = stringRedisTemplate.keys(SKU_SALES_STATISTIC_KEY + "*");
        if (keys != null && !keys.isEmpty()) {
            stringRedisTemplate.delete(keys);
        }
        stringRedisTemplate.delete(PRODUCT_SALES_STATISTIC_KEY);
        log.info("已删除旧数据");

        // 2. 获取已完成且支付成功的订单数据（分页查询）
        int pageSize = 1000; // 每页 1000 条订单
        int pageNo = 1;

        ExecutorService executor = Executors.newFixedThreadPool(10); // 设置线程池，10 个线程并发

        while (true) {
            List<Order> orders = orderMapper.selectList(new QueryWrapper<Order>()
                    .in("orderStatus",
                            OrderStatusEnum.COMPLETED.getValue(),
                            OrderStatusEnum.SHIPPED.getValue(),
                            OrderStatusEnum.REFUNDED.getValue(),
                            OrderStatusEnum.PAID.getValue())
                    .eq("paymentStatus", OrderPayStatusEnum.SUCCESS.getValue())
                    .last("LIMIT " + (pageNo - 1) * pageSize + "," + pageSize));

            if (CollUtil.isEmpty(orders)) {
                break;
            }

            // 执行每一页的处理任务
            executor.submit(() -> processOrders(orders));

            pageNo++;
        }

        // 关闭线程池
        executor.shutdown();
        log.info("统计任务已提交，请等待完成");
    }

    private void processOrders(List<Order> orders) {
        // 3. 获取所有订单涉及的skuId，批量查询商品规格
        Set<Long> skuIds = orders.stream()
                .map(Order::getSkuId)
                .collect(Collectors.toSet());

        List<ProductSKU> skus = productSKUMapper.selectBatchIds(new ArrayList<>(skuIds));
        Map<Long, ProductSKU> skuMap = skus.stream()
                .collect(Collectors.toMap(ProductSKU::getId, sku -> sku));

        // 4. 按商品ID分组统计销量
        Map<Long, Integer> productSalesMap = new HashMap<>(); // 商品总销量
        Map<Long, Map<Long, Integer>> skuSalesMap = new HashMap<>(); // 商品规格销量

        for (Order order : orders) {
            Long skuId = order.getSkuId();
            int quantity = order.getQuantity();

            // 获取商品规格信息
            ProductSKU sku = skuMap.get(skuId);
            if (sku == null) {
                log.warn("订单 {} 对应的商品规格 {} 不存在", order.getId(), skuId);
                continue;
            }
            Long productId = sku.getProductId();

            // 更新商品总销量
            productSalesMap.put(productId, productSalesMap.getOrDefault(productId, 0) + quantity);

            // 更新商品规格销量
            skuSalesMap.computeIfAbsent(productId, k -> new HashMap<>())
                    .merge(skuId, quantity, Integer::sum);
        }

        List<Product> productList = productMapper.selectList(new QueryWrapper<Product>().select("id"));
        for (Product product : productList) {
            stringRedisTemplate.opsForZSet().add(
                    PRODUCT_SALES_STATISTIC_KEY,
                    product.getId().toString(),
                    0
            );
        }
        // 5. 将统计结果写入 Redis
        // 5.1 写入商品总销量（Sorted Set）
        for (Map.Entry<Long, Integer> entry : productSalesMap.entrySet()) {
            stringRedisTemplate.opsForZSet().add(
                    PRODUCT_SALES_STATISTIC_KEY,
                    entry.getKey().toString(),
                    entry.getValue()
            );
        }

        // 5.2 写入商品规格销量（Hash）
        for (Map.Entry<Long, Map<Long, Integer>> entry : skuSalesMap.entrySet()) {
            Long productId = entry.getKey();
            String hashKey = SKU_SALES_STATISTIC_KEY + productId;
            stringRedisTemplate.opsForHash().putAll(hashKey, entry.getValue().entrySet().stream()
                    .collect(Collectors.toMap(
                            e -> e.getKey().toString(),
                            e -> e.getValue().toString()
                    )));
        }
        log.info("统计完成，共处理 {} 个订单", orders.size());
    }
}
